import json
import re

from django.contrib.auth import login, authenticate, logout
from django.shortcuts import render
from apps.users.models import User
# Create your views here.
from django.views import View
from django.http import HttpResponse, JsonResponse
import logging
from django_redis import get_redis_connection
# 创建日志记录器: 导入后创建日志器才能使用
from meiduo_mall.utils.views import LoginRequiredJsonMixin
# 导入celery发送邮件的任务
from celery_tasks.email.tasks import send_email_celery
# 导入加密拼接email url的方法
from apps.users.utils import generate_verify_email_url, check_verify_email_url

logger = logging.getLogger('django')


class UserNameCount(View):
    """
    判断用户重复注册
    """

    def get(self, request, username):
        # 判断用户名是否重复
        try:
            count = User.objects.filter(username=username).count()
        except Exception as e:
            logger.error(e)
            return JsonResponse({
                'code': 400,
                "errmsg": "访问数据库失败"
            })

        return JsonResponse({
            "code": 0,
            "errmsg": "ok",
            "count": count
        })


class MobelsCount(View):

    def get(self, request, mobile):
        try:
            count = User.objects.filter(mobile=mobile).count()
        except Exception as e:
            logger.error(e)
            return JsonResponse({
                "code": 400,
                "errmsg": "访问数据库失败",
            })
        return JsonResponse({
            "code": 0,
            "errmsg": "ok",
            "count": count
        })


class Resgister(View):
    """
    用户注册
    """

    def post(self, request):
        """
        用户注册
        :param request:
        :return:
        """
        # 1 接受数据
        data = request.body.decode()
        data_dict = json.loads(data)
        username = data_dict.get("username")  # 获取用户名
        password = data_dict.get("password")  # 获取用户密码
        password2 = data_dict.get("password2")  # 获取第二次密码
        mobile = data_dict.get("mobile")  # 获取手机号
        sms_code = data_dict.get("sms_code")  # 获取短信验证码
        allow = data_dict.get("allow")  # 是否同意用户协议
        # 2 验证数据
        # 验证数据完整性
        if not all([username, password, password2, mobile, allow]):
            return JsonResponse({
                "code": 400,
                "errmsg": "数据不完整"
            }, status=400)
        # 验证姓名格式
        if not re.match(r"^[a-zA-Z0-9_-]{5,20}$", username):
            return JsonResponse({
                "code": 400,
                "errmsg": "姓名数据格式不正确"
            })
        # 验证密码格式
        if not re.match(r"^[a-zA-Z0-9]{8,20}$", password):
            return JsonResponse({
                "code": 400,
                "errmsg": "密码数据格式不正确"
            })
        # 验证两次密码是否一至
        if password != password2:
            return JsonResponse({
                "code": 400,
                "errmsg": "两次密码不一致"
            })
        # 验证手机号格式
        if not re.match(r"^1[3-9]\d{9}$", mobile):
            return JsonResponse({
                "code": 400,
                "errmsg": "手机号数据格式不正确"
            })
        # 验证短信
        conn = get_redis_connection("verify_code")
        sms_code_server = conn.get('sms_%s' % mobile)
        if not sms_code_server:
            return JsonResponse({
                'code': 400,
                'errmsg': '验证码已过期'

            })
        if sms_code != sms_code_server.decode():
            return JsonResponse({
                'code': 400,
                'errmsg': '短信验证码错误'
            })

        # 验证allow 是否勾选用户协议
        if not allow:
            return JsonResponse({
                "code": 400,
                "errmsg": "allow数据格式不正确"
            })

        # 3 处理逻辑
        # 保存用户数据
        try:
            user = User.objects.create_user(username=username, password=password, mobile=mobile)
        except Exception as e:
            logger.error(e)
            return JsonResponse({
                "code": 400,
                "errmsg": "数据库操作失败"
            })
        # 用户状态保持
        login(request, user)
        # 4 返回数据
        # 写入cook用于网页页面展示
        response = JsonResponse({
            'code': 0,
            'errmsg': 'ok'
        })
        response.set_cookie('username', user.username, max_age=14 * 24 * 3600)
        return response


class LoginView(View):
    def post(self, request):
        '''实现登录接口'''
        # 接受参数
        data_dict = json.loads(request.body.decode())
        username = data_dict.get('username')
        password = data_dict.get('password')
        remembered = data_dict.get('remembered')
        # 效验参数
        if not all([username, password]):
            return JsonResponse({
                'code': 400,
                'errmsg': '数据不完整'
            })
        # 验证密码格式
        if not re.match(r"^[a-zA-Z0-9]{8,20}$", password):
            return JsonResponse({
                'code': 400,
                'errmsg': "用户名或者密码错误"
            })
        # 判断username是用户名还是手机号
        if re.match('1[3-9]/d{9}]', username):
            # 用户输入的是手机号  将username_field指定为mobile字段
            User.USERNAME_FIELD = 'mobile'
        else:
            # 用户输入的是手机号  将username_field指定为username字段
            User.USERNAME_FIELD = 'username'

        # django自带的用户认证方法 其中username=  这个字段在源代码里由username_field指定
        user = authenticate(request=request, username=username, password=password)
        # 判断为空则用户不存在   返回空
        if not user:
            return JsonResponse({
                'code': 400,
                'errmsg': '用户名或者密码错误'
            })

        # 状态保持
        login(request, user)

        # 是否记住用户
        if remembered != True:
            # 不记住登录#  关闭立刻失效
            request.session.set_expiry(0)
        else:
            # 如果记住: 设置为两周有效  默认值为两周
            request.session.set_expiry(None)

        # 写入cook用于网页页面展示
        response = JsonResponse({
            'code': 0,
            'errmsg': 'ok'
        })
        response.set_cookie('username', user.username, max_age=14 * 24 * 3600)
        return response


class LogoutView(View):
    def delete(self, request):
        """
        退出登录
        :param request:
        :return:
        """
        # 清除login写入session的状态保持
        logout(request)
        # 清除cookie数据
        response = JsonResponse({
            "code": 0,
            "errmsg": '退出登录成功'
        })
        response.delete_cookie('username')
        return response


class UserInfoView(LoginRequiredJsonMixin, View):
    def get(self, request):
        """
        用户中心
        :param request:
        :return:
        """
        user = request.user
        # 获取界面需要的数据,进行拼接
        info_data = {
            'username': user.username,
            'mobile': user.mobile,
            'email': user.email,
            'email_active': user.email_active
        }

        # 返回响应
        return JsonResponse({'code': 0,
                             'errmsg': 'ok',
                             'info_data': info_data})


class GetView(View):
    def get(self, request):
        a = User.objects.filter(username=33)
        print(type(a))
        print(a)
        return JsonResponse({
            'code': 000
        })


class EmailView(View):
    def put(self, request):
        """
        添加邮箱
        :param request:
        :return:
        """
        user = request.user
        data_dict = json.loads(request.body.decode())
        email = data_dict.get('email')
        if not email:
            return JsonResponse({
                'code': 400,
                'errmsg': '未传递email参数'
            })
        if not re.match(r'^[a-z0-9][\w\.\-]*@[a-z0-9\-]+(\.[a-z]{2,5}){1,2}$', email):
            return JsonResponse({
                'code': 400,
                'errmsg': '数据格式不正确'
            })
        try:
            user.email = email
            user.save()
        except Exception as e:
            logger.error(e)
            return JsonResponse({
                'code': 400,
                'errmsg': '添加邮箱失败'
            })
        # 调用utils的加密方法 返回拼接好的url
        url = generate_verify_email_url(name=user.username, email=user.email)
        # 调用celery异步处理发送邮件
        # url = "dddddd"
        send_email_celery.delay(email, url)
        # send_email_celery(email, url)
        return JsonResponse({
            'code': 0,
            'errmsg': 'ok'
        })


class EmailVerficationView(View):
    def put(self, request):
        """
        验证邮箱
        :param request:
        :return:
        """
        token = request.GET.get('token')
        if not token:
            return JsonResponse({
                'code': 400,
                'errmsg': "未传递token"
            })
        name, email = check_verify_email_url(token)
        try:
            user = User.objects.get(username=name, email=email)
        except Exception:
            return JsonResponse({
                'code': 400,
                'errmsg': '无效的token'
            })
        try:
            user.email_active = 1
            user.save()
        except Exception:
            return JsonResponse({
                'code': 400,
                'errmsg': '验证失败'
            })
        return JsonResponse({
            'code': 0,
            'errmsg': 'ok'
        })


class ChangePasswordView(View):
    def put(self, request):
        """
        修改密码
        :param request:
        :return:
        """
        # 接收参数
        dict = json.loads(request.body.decode())
        old_password = dict.get('old_password')
        new_password = dict.get('new_password')
        new_password2 = dict.get('new_password2')

        # 校验参数
        if not all([old_password, new_password, new_password2]):
            return JsonResponse({'code': 400,
                                 'errmsg': '缺少必传参数'})

        result = request.user.check_password(old_password)
        if not result:
            return JsonResponse({'code': 400,
                                 'errmsg': '原始密码不正确'})

        if not re.match(r'^[0-9A-Za-z]{8,20}$', new_password):
            return JsonResponse({'code': 400,
                                 'errmsg': '密码最少8位,最长20位'})

        if new_password != new_password2:
            return JsonResponse({'code': 400,
                                 'errmsg': '两次输入密码不一致'})
        try:
            # 修改密码
            request.user.set_password(new_password)
            request.user.save()
        except Exception as e:
            logger.error(e)
            return JsonResponse({'code': 400, 'errmsg': '修改失败'})

        # 清楚保持状态
        logout(request)
        response = JsonResponse({'code': 0, 'errmsg': 'ok'})
        response.delete_cookie('username')
        return response
